/**
 * @project_name thread
 * @package_name com.gxwz.thread
 * @file_name Java5SpecificConditionInterface4Thread.java
 */
package com.gxwz.thread;


/**
 * 一道面试题： 子线程循环10次，接着主线程循环10次， 在回到子线程循环10次，再回到主线程循环10次。
 * 
 * @author chendequan
 * @email 1527254027@qq.com
 * @datetime 2013-9-5 下午11:37:37
 * 
 */
public class Java5SpecificConditionInterface4Thread {
	public static void main(String[] args) throws InterruptedException {
		final Business business = new Business();
//		创建一个新的线程并启动；这个是子线程
		new Thread(new Runnable() {  //Thread 的构造函数不接受Callable接口作为参数
			/*
			 * (non-Javadoc)
			 * 
			 * @see java.lang.Runnable#run()
			 */
			@Override
			public void run() {
				try {
					for (int i = 0; i < 2; i++) 
						business.sub();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}).start();

		/*
		 * 关键是怎么才能让子线程执行了一次之后休眠;
		 * 开始执行主线程,主线程执行完成之后休眠;
		 * 再执行子线程,执行完毕后休眠再执行主线程;
		 */
		
//		这是在主线程里执行的
		for (int i = 0; i < 2; i++)
			business.main();
	}

}

class Business {
//	这个标志非常重要，正是由于这个标志才使得主线程和子线程执行顺序随意切换；
	private boolean bShouldSub = true;

	/**
	 * @datetime 2013-9-6 上午01:32:28
	 */
	public synchronized void sub() throws InterruptedException {
		/*
		 * 首次执行到这里时，bShouldSub为true，不等待；
		 * 之后直接执行for循环；
		 */
		while (!bShouldSub)
			this.wait();
		
		for (int j = 1; j <= 10; j++)
			System.out.println("sub thread sequence of " + j);
		
		bShouldSub = false;
		
//		 唤醒在此对象监视器上等待的单个线程。
		this.notify();
	}
	
	public synchronized void main() throws InterruptedException {
		/*
		 * 首次执行到这里时，bShouldSub为false，主线程等待；
		 * 由于线程是并行的，且主线程处在等待状态，所以自然的执行到了子线程；
		 * 子线程的for循环执行完毕之后执行this.notify()函数，唤醒了等待的主线程；
		 * 此时主线程和子线程处于并行的状态；
		 * 但是此时程序仍然在
		 * for (int i = 0; i < 2; i++) 
		 * 		business.sub();
		 * 继续执行sub函数，只是此时的bShouldSub为false则，
		 * while (!bShouldSub)
		 *	this.wait();
		 * 子线程处于等待状态而主线程去没有处在等待状态，所以此时先执行了46行的main函数的for循环；
		 * for循环执行完毕后执行this.notify()函数唤醒了所有等待的线程；
		 * 此时主线程和子线程都准备执行关键就是看状态标志bShouldSub了；
		 * 此时的又回到前面说的。先执行了子线程再执行主线程；
		 * 如此实现了题目的要求，标志bShouldSub和wait、notify函数很关键
		 */
		while (bShouldSub)
			this.wait();
		
		for (int j = 1; j <= 10; j++)
			System.out.println("main thread sequence of " + j);
		
		bShouldSub = true;
		
		this.notify();
	}

}

//子线程循环10次，
//接着主线程循环10次， 
//再回到子线程循环10次，
//再回到主线程循环10次。
//------------------结果===============
//sub thread sequence of 1
//sub thread sequence of 2
//sub thread sequence of 3
//sub thread sequence of 4
//sub thread sequence of 5
//sub thread sequence of 6
//sub thread sequence of 7
//sub thread sequence of 8
//sub thread sequence of 9
//sub thread sequence of 10
//main thread sequence of 1
//main thread sequence of 2
//main thread sequence of 3
//main thread sequence of 4
//main thread sequence of 5
//main thread sequence of 6
//main thread sequence of 7
//main thread sequence of 8
//main thread sequence of 9
//main thread sequence of 10
//sub thread sequence of 1
//sub thread sequence of 2
//sub thread sequence of 3
//sub thread sequence of 4
//sub thread sequence of 5
//sub thread sequence of 6
//sub thread sequence of 7
//sub thread sequence of 8
//sub thread sequence of 9
//sub thread sequence of 10
//main thread sequence of 1
//main thread sequence of 2
//main thread sequence of 3
//main thread sequence of 4
//main thread sequence of 5
//main thread sequence of 6
//main thread sequence of 7
//main thread sequence of 8
//main thread sequence of 9
//main thread sequence of 10

